//<script>
//////////////////
// Helper Stuff //
//////////////////

// used to find the Automation server name
function getDomDocumentPrefix() {
	if (getDomDocumentPrefix.prefix)
		return getDomDocumentPrefix.prefix;
	
	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
	var o;
	for (var i = 0; i < prefixes.length; i++) {
		try {
			// try to create the objects
			o = new ActiveXObject(prefixes[i] + ".DomDocument");
			return getDomDocumentPrefix.prefix = prefixes[i];
		}
		catch (ex) {};
	}
	
	throw new Error("Could not find an installed XML parser");
}

function getXmlHttpPrefix() {
	if (getXmlHttpPrefix.prefix)
		return getXmlHttpPrefix.prefix;
	
	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
	var o;
	for (var i = 0; i < prefixes.length; i++) {
		try {
			// try to create the objects
			o = new ActiveXObject(prefixes[i] + ".XmlHttp");
			return getXmlHttpPrefix.prefix = prefixes[i];
		}
		catch (ex) {};
	}
	
	throw new Error("Could not find an installed XML parser");
}

//////////////////////////
// Start the Real stuff //
//////////////////////////


// XmlHttp factory 
var XmlHttp = {
	create : function () {
		try {
			if (window.XMLHttpRequest) {
				var req = new XMLHttpRequest();
				
				// some versions of Moz do not support the readyState property
				// and the onreadystate event so we patch it!
				if (req.readyState == null) {
					req.readyState = 1;
					req.addEventListener("load", function () {
						req.readyState = 4;
						if (typeof req.onreadystatechange == "function")
							req.onreadystatechange();
					}, false);
				}
				
				return req;
			}
			if (window.ActiveXObject) {
				return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp");
			}
		}
		catch (ex) { alert ("Your browser does not support XmlHttp objects") }
		// fell through
		throw new Error("Your browser does not support XmlHttp objects");
	}
} 

// XmlDocument factory
var XmlDocument = {
	create : function () {
		try {
			// DOM2
			if (document.implementation && document.implementation.createDocument) {
				var doc = document.implementation.createDocument("", "", null);
				
				// some versions of Moz do not support the readyState property
				// and the onreadystate event so we patch it!
				if (doc.readyState == null) {
					doc.readyState = 1;
					doc.addEventListener("load", function () {
						doc.readyState = 4;
						if (typeof doc.onreadystatechange == "function")
							doc.onreadystatechange();
					}, false);
				}
				
				
				return doc;
			}
			if (window.ActiveXObject)
				return new ActiveXObject(getDomDocumentPrefix() + ".DomDocument");
		}
		catch (ex) { alert ("Your browser does not support XmlDocument objects") }
		throw new Error("Your browser does not support XmlDocument objects");
	}	
} 

// SAX factory
var SAX = { 
	/*
	 * SAX parser
	 *
	 * This serializes a collection of nodes into objects
	 * ------------------------------------------------------------------------------------------
	 * Usage: 	var oSAX = SAX.create (document[, recordname][, fieldname][, type][, decoration])
	 *        	while (!oSAX.eof)
	 *        	{
	 *             	// do stuff with oSAX.current;
	 *            	oSAX.movenext(); 
	 *        	} 
	 * 
	 * Where: 
	 *        	document	is the document or parent element to be parsed
	 *			recordname	is name to designate records, i.e. <record/> (default 'record') 
	 *			fieldname	(for SAX.types.CHILDNODE) is name to designate field names, i.e.  
	 *                        <field name="fieldname">data</field>  
	 *                      (default 'name')
	 *          type		is the type of parsing (SAX.types.CHILDNODE or SAX.types.ATTRIBUTE) 
	 *                      (default SAX.types.CHILDNODE)
	 *			decoration	is an optional function used to decorate serialized objects with 
	 *						extra properties and/or methods
	 * ------------------------------------------------------------------------------------------ 
	 *
	 */
	types 	: {CHILDNODE:0, ATTRIBUTE:1},
	create	: function (element, recordname, fieldname, type, decoration)
	{ // begin create
		var object = {
			// user set params
			element     : element,
			recordname  : recordname||'record',
			fieldname   : fieldname||'name',
			type  		: type||SAX.types.CHILDNODE,
			decoration 	: decoration,
			
			// preset params
			eof         : false, 
			index       : -1,
			step        : 1,
			current		: {},
			movefirst 	: function ()
			{
				this.index = 0; this.eof = this.sync ();
			}, 
			movenext 	: function ()
			{
				this.index += this.step; this.eof = this.sync ();  
			},
			load 		: function (array)
			{
			    this.movefirst();
				while(!this.eof) { array.push (this.current); this.movenext(); } 
			}, 
			serialize	: function (node)
			{  
				var name,o={};if (this.type==SAX.types.ATTRIBUTE) {
				for (var x=0;x<node.attributes.length;x++)
				o[ node.attributes[x].name ] = node.attributes[x].value;
				o['#text'] = node.firstChild ? node.firstChild.nodeValue :
				node.nodeValue; } else if (this.type==SAX.types.CHILDNODE)
				{ for (var i=0;i<node.childNodes.length;i++)  
				  { if (node.childNodes[i].nodeType==1) { 
				      name = node.childNodes[i].getAttribute(this.fieldname);  
				      o [name] = node.childNodes[i].firstChild ? 
				      node.childNodes[i].firstChild.nodeValue : 
					  node.childNodes[i].nodeValue; } }
				} return o;
			},
			sync 		: function ()
			{  
				var name, node, collection = this.element.getElementsByTagName (this.recordname);
				this.current = {}; 
				if (collection)
				{ 
					if (this.index < collection.length)
					{
						node = collection [this.index]; 
						this.current = this.serialize (node);
						if (this.decoration) 
						{
							this.current = this.decoration(this.current);
						}
						return false;
					} 
				}
				return true; 
			} 
		} 
		object.movefirst();
		return object;
	} // end create
} 


// Create the loadXML method and xml getter for Mozilla
if (window.DOMParser &&
	window.XMLSerializer &&
	window.Node && Node.prototype && Node.prototype.__defineGetter__) {

	// XMLDocument did not extend the Document interface in some versions
	// of Mozilla. Extend both!
	//XMLDocument.prototype.loadXML = 
	
	Document.prototype.loadXML = function (s) {
		
		// parse the string to a new doc	
		var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
		
		// remove all initial children
		while (this.hasChildNodes())
			this.removeChild(this.lastChild);
			
		// insert and import nodes
		for (var i = 0; i < doc2.childNodes.length; i++) {
			this.appendChild(this.importNode(doc2.childNodes[i], true));
		}
		
		return true;
	};
	 
	
	/*
	 * xml getter
	 *
	 * This serializes the DOM tree to an XML String
	 *
	 * Usage: var sXml = oNode.xml
	 *
	 */
	// XMLDocument did not extend the Document interface in some versions
	// of Mozilla. Extend both!
	/*
	XMLDocument.prototype.__defineGetter__("xml", function () {
		return (new XMLSerializer()).serializeToString(this);
	});
	*/
	Document.prototype.__defineGetter__("xml", function () {
		return (new XMLSerializer()).serializeToString(this);
	});
}
